#include "drv_btn.h"
#include "public_datas.h"

#define TAG "BTN"

typedef void (*btn_event_cb_t)(btn_event_t event);

#define HOLD_WAKE_TIME_MS (btn_double_click_time_default + 20) // 有按键事件保持系统唤醒时长
#define BTN_HEARTBEAT_MS 5

static int16_t hold_time = HOLD_WAKE_TIME_MS;
static btn_event_cb_t btn_cb = NULL;
static uint8_t busy = 0;

static void drv_btn_register_cb(void *arg, size_t len)
{
    btn_cb = (btn_event_cb_t)arg;
}

static int gpio_read_level(uint8_t io)
{
    return (gpio_get_level(io));
}

static void btn_handler_cb(void *arg)
{

    btn_handler();
    hold_time -= BTN_HEARTBEAT_MS;

    if (btn_available())
    {
        hold_time = HOLD_WAKE_TIME_MS;
        uint8_t io;
        btn_event_t ret;
        btn_read_event(&io, &ret);
        esay_logd(TAG, "key %d event: %d\n", io, ret);

        if (io == BTN_USB) // USB插入识别
        {
            if (ret == btn_long_press)
            {
                topic_messenger_msg("usb_conn", NULL, 0);
                btn_attach(UART_RTS, LOW);
                gpio_it_enable(UART_RTS, ENABLE);

                // esay_logi(TAG, "usb conn");
                // gpio_set_mode(KEY_POWER, GPIO_MODE_OUT_PUSHPULL_5mA);
                // gpio_set_level(KEY_POWER, 1);
            }
            else if (ret == btn_up)
            {
                // esay_logi(TAG, "usb disconn");
                gpio_it_enable(UART_RTS, DISABLE);
                btn_detach(UART_RTS);
                topic_messenger_msg("usb_disconn", NULL, 0);
                // gpio_set_mode(KEY_POWER, GPIO_MODE_OUT_PUSHPULL_5mA);
                // gpio_set_level(KEY_POWER, 0);
#if DEBUG_KEEP_WAKE_EN
                busy--;
#endif
            }
            else if (ret == btn_down)
            {
#if DEBUG_KEEP_WAKE_EN
                busy++;
#endif
            }
        }
        else if (io == BTN_POWER) // 电源按键
        {
            if (ret == btn_down)
            {
                busy++;
            }
            else if (ret == btn_up)
            {
                busy--;
            }
            else if (ret == btn_long_press)
            {
#if BTN_POWER_LONG_PRESS_PROGRAM
                restart_sys(restart_sys_iap);
#endif
            }
            if (btn_cb)
                btn_cb(ret);
        }
        else // UART RTS检测
        {
            if (ret == btn_down)
            {
                busy++;
                gpio_set_level(SF32_EN, LOW);
            }
            else if (ret == btn_up)
            {
                busy--;
                gpio_set_level(SF32_EN, HIGH);
            }
        }
    }

    if (busy || hold_time > 0)
    {
        public_task_start(btn_handler_cb, NULL, BTN_HEARTBEAT_MS);
    }
}

static void gpio_it_cb(gpio_t io)
{
    if (hold_time <= 0 && busy == 0)
    {
        hold_time = HOLD_WAKE_TIME_MS;
        public_task_start(btn_handler_cb, NULL, BTN_HEARTBEAT_MS);
    }

    if (public_datas()->sleep_state == DISABLE) // 工作中不设置唤醒原因
        return;

    switch (io)
    {
    case BTN_POWER:
        public_datas()->wake_rason = WAKE_BY_BTN;
        break;
    case BTN_USB:
        public_datas()->wake_rason = WAKE_BY_USB;
        break;
    case UART_RTS:
        public_datas()->wake_rason = WAKE_BY_SF_PROG;
        break;
    default:
        break;
    }
}

void drv_btn_install()
{

    gpio_set_mode(BTN_POWER, GPIO_MODE_IN_PULLUP);

#if BTN_POWER_LONG_PRESS_PROGRAM
    while (gpio_get_level(BTN_POWER) == 0)
        ;
#endif

    btn_attach_read_io_func(gpio_read_level);
    btn_attach(BTN_POWER, 0);
    btn_attach(BTN_USB, 1);

    btn_register_get_tic_cb(public_sys_tick_get);

    if (public_datas()->usb_sta)
        public_task_start(btn_handler_cb, NULL, BTN_HEARTBEAT_MS);

    gpio_register_it_cb(gpio_it_cb);

    gpio_it_mode(BTN_POWER, IT_FALL_EDGE);
    gpio_it_mode(UART_RTS, IT_FALL_EDGE);
    gpio_it_mode(BTN_USB, IT_RISE_EDGE);

    gpio_it_enable(UART_RTS, DISABLE);

    PWR_PeriphWakeUpCfg(ENABLE, RB_SLP_GPIO_WAKE, Short_Delay);

    topic_messenger_subscribe(NULL, "btn_set_event_cb", drv_btn_register_cb);
}
